import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { Row, Col, Form, Input, Radio, Button } from 'antd';
import { Icon } from 'react-fa';
import Grid from '@/components/Grid';
import Layout from '@/components/Layout';
import Dialog, { withRef } from '@/components/Dialog';
import settings, { getPagination } from '@/settings';
import { $request, $http } from '@/utils/request';
import { mapping } from '@/utils'

@Form.create()
@connect(({ dictionary: { data } }) => ({ data }))
@withRef
class ModelForm extends React.Component {
  formLayout = {
    labelAlign: 'left',
    labelCol: {
      span: 4
    },
    wrapperCol: {
      span: 20
    },
  };
  handleSubmit = (_, callback) => {
    const { form } = this.props;

    form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        callback(values);
      }
    });
  };
  render() {
    const {
      id,
      data = {},
      form: { getFieldDecorator },
    } = this.props;

    return (
      <Form layout="vertical">
        <Form.Item label="数据类型：" {...this.formLayout}>
          {getFieldDecorator('type', {
            initialValue: data.name,
          })(<Radio.Group>
            <Radio value="1">普通类型</Radio>
            <Radio value="2">树形结构</Radio>
          </Radio.Group>)}
        </Form.Item>
        <Form.Item label="字典表名">
          {getFieldDecorator('name', {
            rules: [
              {
                required: true,
                message: '请输入字典表名',
              },
              {
                validator: (rule, value, callback) => {
                  if (!value || value.trim() === '') {
                    callback()
                    return
                  }
                  $http
                    .post('valid/dictionaryname', {
                      data: {
                        id,
                        value,
                      },
                      type: true,
                      requestType: 'form',
                    })
                    .then(data => {
                      data.valid ? callback() : callback('字典名称已存在');
                    });
                },
              },
            ],
            initialValue: data.name,
          })(<Input placeholder="请输入" />)}
        </Form.Item>
        <Form.Item label="显示名称">
          {getFieldDecorator('title', {
            rules: [
              {
                required: true,
                message: '请输入显示名称',
              },
            ],
            initialValue: data.title,
          })(<Input placeholder="请输入" />)}
        </Form.Item>
        <Form.Item label="字典描述">
          {getFieldDecorator('desc', {
            rules: [
              {
                message: '请输入至少五个字符的部门描述！',
                min: 5,
              },
            ],
            initialValue: data.desc,
          })(<Input.TextArea rows={8} placeholder="请输入至少五个字符" />)}
        </Form.Item>
      </Form>
    );
  }
}

const swap = (array, x, y) => {
  array[x] = array.splice(y, 1, array[x])[0];
  return array;
}

let id = 0

@Form.create()
@connect(({ dictionary: { data = {}, fields = [] } }) => ({ data, fields }))
@withRef
class ModelListForm extends React.Component {
  formLayout = {
    labelAlign: 'left',
    labelCol: {
      span: 4
    },
    wrapperCol: {
      span: 20
    },
  };
  handleSubmit = (_, callback) => {
    const { form } = this.props;

    form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        callback(values);
      }
    });
  };
  handleMenuEvent(e, key, index) {
    e.stopPropagation()

    const {
      form: {
        getFieldValue,
        setFieldsValue
      }
    } = this.props

    const keys = getFieldValue('keys');

    switch (key) {
      case 'add':
        const nextKeys = keys.concat(id++);
        setFieldsValue({
          keys: nextKeys,
        });
        break
      case 'remove':
        if (keys.length === 1) {
          return;
        }

        keys.splice(index, 1)

        setFieldsValue({
          keys
        });
        break
      case 'movePrev':
        if (index > 0) {
          const curName = getFieldValue(`fields[${index}].name`);
          const curValue = getFieldValue(`fields[${index}].value`);
          const prevName = getFieldValue(`fields[${index - 1}].name`);
          const prevValue = getFieldValue(`fields[${index - 1}].value`);

          setFieldsValue({
            [`fields[${index - 1}].name`]: curName,
            [`fields[${index - 1}].value`]: curValue,
            [`fields[${index}].name`]: prevName,
            [`fields[${index}].value`]: prevValue
          })
          swap(keys, index, index - 1);
          setFieldsValue({
            keys,
          });
        }
        break
      case 'moveNext':
        if (index < keys.length - 1) {
          const curName = getFieldValue(`fields[${index}].name`);
          const curValue = getFieldValue(`fields[${index}].value`);
          const nextName = getFieldValue(`fields[${index + 1}].name`);
          const nextValue = getFieldValue(`fields[${index + 1}].value`);

          setFieldsValue({
            [`fields[${index + 1}].name`]: curName,
            [`fields[${index + 1}].value`]: curValue,
            [`fields[${index}].name`]: nextName,
            [`fields[${index}].value`]: nextValue
          })
          swap(keys, index, index + 1);
          setFieldsValue({
            keys,
          });
        }
        break
      default:
    }
  };
  componentDidMount() {
    const {
      id,
      dispatch
    } = this.props;

    if (id) {
      dispatch({
        type: 'dictionary/fetchList',
        payload: {
          id
        }
      });
    }
  };
  render() {
    const {
      data,
      fields,
      form: { getFieldValue, getFieldDecorator },
    } = this.props;

    const initialValue = fields.map(_ => ++id)

    getFieldDecorator('keys', { initialValue });
    const keys = getFieldValue('keys');

    return (
      <Form layout="vertical">
        <Form.Item label="字典表名" {...this.formLayout}>
          {data.name || '测试表名'}
        </Form.Item>
        <div className="field-options">
          {
            keys.map((_, index) => {
              const field = fields[index] || {}
              return (
                <div className="field-option" key={index}>
                  <div className="field-option-body">
                    {
                      <div className="field-option-form">
                        <Row gutter={8}>
                          <Col span={12}>
                            <Form.Item>
                              {getFieldDecorator(`fields[${index}].name`, {
                                initialValue: field.name,
                              })(<Input placeholder="请输入键名" />)}
                            </Form.Item>
                          </Col>
                          <Col span={12}>
                            <Form.Item>
                              {getFieldDecorator(`fields[${index}].value`, {
                                initialValue: field.value,
                              })(<Input placeholder="请输入键值" />)}
                            </Form.Item>
                          </Col>
                        </Row>
                      </div>
                    }
                  </div>
                  <div className="field-option-footer">
                    {index !== 0 && <span className="ico-btn text-danger" onClick={e => this.handleMenuEvent(e, 'remove', index)}><Icon name="minus-square" /></span>}
                    {index === keys.length - 1 && <span className="ico-btn" onClick={e => this.handleMenuEvent(e, 'add', index)}><Icon name="plus-square" /></span>}
                    <span className="ico-btns">
                      {index !== 0 && <span className="ico-btn" onClick={e => this.handleMenuEvent(e, 'movePrev', index)}><Icon name="caret-up" /></span>}
                      {index !== keys.length - 1 && <span className="ico-btn" onClick={e => this.handleMenuEvent(e, 'moveNext', index)}><Icon name="caret-down" /></span>}
                    </span>
                  </div>
                </div>
              )
            })
          }
        </div>
      </Form>
    );
  }
}

@Form.create()
@connect(({ dictionary: { data = {} } }) => ({ data }))
@withRef
class ModelTreeForm extends React.Component {
  formLayout = {
    labelAlign: 'left',
    labelCol: {
      span: 4
    },
    wrapperCol: {
      span: 20
    },
  };
  handleSubmit = (_, callback) => {
    const { form } = this.props;

    form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        callback(values);
      }
    });
  };
  componentDidMount() {
    const {
      id,
      dispatch
    } = this.props;

    if (id) {
      dispatch({
        type: 'dictionary/fetchTree',
        payload: {
          id
        }
      });
    }
  };
  render() {
    const {
      data,
    } = this.props;

    return (
      <Form layout="vertical">
        <Form.Item label="字典表名" {...this.formLayout}>
          {data.name}
        </Form.Item>
      </Form>
    );
  }
}

@connect(({ app: { user = {} }, dictionary: { list = {}, params }, loading }) => ({
  user,
  list,
  params,
  loading: loading.effects['dictionary/fetchAll'],
}))
@Form.create()
class DictionaryPage extends PureComponent {
  state = {
    selectedRows: [],
  };
  types = [{
    name: '普通类型',
    value: 1
  }, {
    name: '树状结构',
    value: 2
  }]
  columns = [
    {
      title: '字典表名',
      dataIndex: 'name',
      width: 200,
    },
    {
      title: '显示名称',
      dataIndex: 'title',
      width: 200,
    },
    {
      title: '类型',
      dataIndex: 'type',
      width: 200,
      render: (v, record, index) => mapping(v, this.types)
    },
    {
      title: '操作',
      width: 200,
      align: 'center',
      render: (v, record, index) => {
        const { type } = record
        return (
          <span
            className="btn-text"
            onClick={e => this.handleMenuEvent(e, 'setting', type)}>
            <Icon
              name="gear"
              title="数据设置"
            />
          </span>
        )
      }
    },
  ];
  componentDidMount() {
    const { dispatch } = this.props;
    dispatch({
      type: 'dictionary/fetchAll',
    });
  };
  handleMenuEvent(e, key, type) {
    e.stopPropagation()
    const { dispatch } = this.props;
    dispatch({
      type: 'dictionary/reset',
    });
    switch (key) {
      case 'setting':
        if (type === 1) {
          Dialog.drawer({
            title: '普通类型配置',
            width: 480,
            component: ModelListForm
          })
        } else if (type === 2) {
          Dialog.drawer({
            title: '树状结构配置',
            width: 640,
            component: ModelTreeForm
          })
        }
        break;
      default:
    }
  };
  handleSelectRows = rows => {
    this.setState({
      selectedRows: rows,
    });
  };
  handleAdd = e => {
    const { dispatch } = this.props;
    dispatch({
      type: 'dictionary/reset',
    });
    Dialog.open({
      title: '选择字典类型',
      fixed: true,
      url: 'dictionary/add',
      component: ModelForm,
      onOk: data => {
        this.handleReload();
      }
    });
  };
  handleEdit = e => {
    const { selectedRows } = this.state;
    const { id } = selectedRows[0];
    const { dispatch } = this.props;
    dispatch({
      type: 'dictionary/reset',
    });
    Dialog.open({
      title: '修改字典',
      fixed: true,
      url: 'dictionary/update',
      data: {
        id,
      },
      options: {
        type: 'put',
      },
      onOk: data => {
        this.handleReload();
      },
      component: props => <ModelForm {...props} id={id} />,
      connect: ({ loading }) => ({ loading: loading.effects['dictionary/fetchOne'] }),
    });
  };
  handleRemove = e => {
    const { selectedRows } = this.state;
    Dialog.confirm({
      title: '确认提示',
      content: '确定要删除已选择的字典？',
      onOk: () => {
        $request
          .put('dictionary/delete', {
            id: selectedRows.map(_ => _.id),
          })
          .then(data => {
            this.handleReload();
          });
      },
    });
  };
  handleGridChange = (oldPagination, sorter) => {
    const { params, dispatch } = this.props;

    const pagination = getPagination(oldPagination);
    const payload = {
      ...params,
      ...pagination,
    };

    if (sorter.field) {
      payload.sorter = sorter.field;
      payload.order = sorter.order;
    }

    dispatch({
      type: 'dictionary/fetchAll',
      payload,
    });
  };
  handleReload = () => {
    const { params, dispatch } = this.props;
    dispatch({
      type: 'dictionary/fetchAll',
      payload: params,
    });
  };
  handleSearch = (value, e) => {
    e.preventDefault();
    const { params, dispatch } = this.props;
    const pagination = getPagination({
      pageNumber: 1,
    });
    dispatch({
      type: 'dictionary/fetchAll',
      payload: {
        ...params,
        ...pagination,
        name: value,
      },
    });
  };
  render() {
    const { selectedRows } = this.state;
    const {
      params,
      loading,
      list: { data, total },
    } = this.props;

    const pageNumber = params[settings.pageNumber];
    return (
      <Layout
        header={{
          icon: 'book',
          title: '数据字典',
        }}
        toolbar={{
          left: (
            <React.Fragment>
              <Button type="primary" onClick={this.handleAdd}>
                新建
              </Button>
              <Button onClick={this.handleEdit} disabled={selectedRows.length !== 1}>
                编辑
              </Button>
              <Button
                type="danger"
                disabled={selectedRows.length === 0}
                onClick={this.handleRemove}
              >
                删除
              </Button>
            </React.Fragment>
          ),
          right: (
            <Form layout="inline">
              <Input.Search placeholder="请输入要查询的关键词" onSearch={this.handleSearch} />
            </Form>
          ),
        }}
      >
        <Grid
          selectedRows={selectedRows}
          onSelectRow={this.handleSelectRows}
          columns={this.columns}
          data={data}
          loading={loading}
          pagination={{
            pageNumber,
            total,
          }}
          onReload={this.handleReload}
          onChange={this.handleGridChange}
        />
      </Layout>
    );
  }
}

export default DictionaryPage;
